'use strict';
var gulp = require('gulp'),
    path = require('path'),
    del = require('del'),
    open = require('open'),
    chalk = require('chalk'),
    runSequence = require('run-sequence'),
    streamqueue = require('streamqueue'),
    stylish = require('jshint-stylish'),
    plugins = require('gulp-load-plugins')();

var args = require('yargs')
    .alias('b', 'build')
    .alias('h', 'help')
    .alias('p', 'protocol')
    .alias('s', 'serverIp')
    .alias('t', 'port')
    .alias('d', 'debug')
    .default('debug', false)
    .default('build', false)
    .default('port', 9002)
    .default('protocol', 'http://')
    .argv;

var appName = 'mjh';
var build = !!args.build;
var debug = !!args.debug;
var port = args.port;
var targetDir = path.resolve(build ? 'www' : '.tmp');
var isNewIp = !!args.serverIp && !!args.protocol;
var serverUrl = args.protocol + args.serverIp;
var env = process.env.NEC_ENV || 'local'; // 暴露 NEC_ENV 环境变量

/**
 * 命令帮助
 */
gulp.task('help', function() {
    var chalkLog = chalk.red.bold;
    console.log(chalkLog('   gulp [参数 值 参数 值..]   调用形式'));
    console.log(chalkLog('   gulp -b     文件压缩编译打包'));
    console.log(chalkLog('   gulp -d     代码调试'));
    console.log(chalkLog('   gulp -h     gulp参数说明'));
    console.log(chalkLog('   gulp -p     传输协议，默认http://'));
    console.log(chalkLog('   gulp -s     后端IP地址，需要端口号'));
    console.log(chalkLog('   gulp -t     前端测试服务端口号，默认9000'));
});

/**
 * 本地测试服务
 * @param  {[type]}
 * @return {[type]}   [description]
 */
gulp.task('serve', function() {
    plugins.connect.server({
        root: [targetDir],
        port: port,
        livereload: true
    });
    open('http://localhost:' + port + '/index.html');
});

/**
 * 编译SCSS文件到指定目录
 * @param  {[type]}
 * @return {[type]}   [description]
 */
gulp.task('styles', function() {
    var sassOptions = build ? {
        style: 'compressed'
    } : {
        style: 'expanded'
    };

    var sassStream = plugins.rubySass('src/styles/main.scss', sassOptions)
        .pipe(plugins.autoprefixer({
            browsers: ['last 5 version']
        }));
    var revImgStream = gulp.src(['dist/**/*.json']);
    var revCssStream = streamqueue({
            objectMode: true
        }, revImgStream, sassStream)
        .pipe(plugins.revCollector());

    var vendorFiles = require('./vendorCss.json');

    var cssStream = gulp.src(vendorFiles)
        .pipe(plugins.concat('vendor.css'));
    return streamqueue({
            objectMode: true
        }, cssStream, revCssStream)
        .pipe(plugins.concat('main.css'))
        .pipe(plugins.if(build, plugins.minifyCss({
            processImport: false
        })))
        .pipe(plugins.if(build, plugins.rev()))
        .pipe(gulp.dest(path.join(targetDir, 'styles')));
});

/**
 * 连接生成第三方js文件
 * @param  {[type]}
 * @return {[type]}   [description]
 */
gulp.task('vendor', function() {
    var vendorFiles = require('./vendor.json');

    return gulp.src(vendorFiles)
        .pipe(plugins.concat('vendor.js'))
        .pipe(plugins.if(build, plugins.uglify()))
        .pipe(plugins.if(build, plugins.rev()))
        .pipe(gulp.dest(targetDir));
});

/**
 * 生成templates的view到angular的templateCache,然后和项目的js合并
 * @param  {[type]}
 * @return {[type]}   [description]
 */
gulp.task('scripts', function() {
    var dest = path.join(targetDir, 'scripts');

    var configStream = gulp.src('src/config/config.json')
        .pipe(plugins.ngConfig(appName, {
            createModule: false,
            environment: env
        }))
        .pipe(plugins.if(isNewIp,
            plugins.injectString.before('.constant(\'serverUrl\'',
                '\n.constant(\'serverUrl\',\'' + serverUrl + '\')\n//')));

    var templateStream = gulp
        .src(['dist/**/*.json', 'src/views/**/*.html'])
        .pipe(plugins.revCollector())
        .pipe(plugins.naturalSort())
        .pipe(plugins.minifyHtml({
            empty: true,
            spare: true,
            quotes: true
        }))
        .pipe(plugins.angularTemplatecache('templates.js', {
            root: 'views/',
            module: appName
        }));

    var appStream = gulp.src('src/scripts/app.js')
        .pipe(plugins.if(build,
            plugins.replace('html5Mode(false)', 'html5Mode(true)')));
    //获取所有定义module的js，如：common/commonModule.js
    var moduleStream = gulp.src(['*/*.js'], {
            cwd: 'src/scripts'
        })
        .pipe(plugins.naturalSort())
        .pipe(plugins.if(!build, plugins.changed(dest)));
    //获取所有模块下的js,排除掉了定义module的js, 如：common/utils/[文件夹/](可有可无)*.js
    var scriptStream = gulp.src(['dist/**/*.json', 'src/scripts/*/*/**/*.js'])
        .pipe(plugins.revCollector())
        .pipe(plugins.naturalSort())
        .pipe(plugins.if(!build, plugins.changed(dest)));

    return streamqueue({
            objectMode: true
        }, appStream, moduleStream, scriptStream, templateStream, configStream)
        .pipe(plugins.if(build, plugins.ngAnnotate()))
        .pipe(plugins.if(build, plugins.stripDebug()))
        .pipe(plugins.if(build, plugins.sourcemaps.init()))
        .pipe(plugins.if(build, plugins.concat('app.js')))
        .pipe(plugins.if(build, plugins.uglify()))
        .pipe(plugins.if(debug, plugins.sourcemaps.write()))
        .pipe(plugins.if(build, plugins.rev()))
        .pipe(gulp.dest(dest));
});

/**
 * 字体复制
 * @param  {[type]}
 * @return {[type]}   [description]
 */
gulp.task('fonts', function() {
    gulp.src(['src/fonts/*.*'])
        .pipe(gulp.dest(path.join(targetDir, 'fonts')));
    return gulp.src(['bower_components/bootstrap-sass/assets/fonts/bootstrap/*.*'])
        .pipe(gulp.dest(path.join(targetDir, 'fonts/bootstrap')));
});

/**
 * 图片复制
 * @param  {[type]} )
 * @return {[type]}   [description]
 */
gulp.task('images', function() {
    return gulp.src('src/images/**/*.*')
        .pipe(plugins.if(build, plugins.imagemin({
            progressive: true
        })))
        .pipe(plugins.if(build, plugins.rev()))
        .pipe(gulp.dest(path.join(targetDir, 'images')))
        .pipe(plugins.rev.manifest())
        .pipe(gulp.dest('dist/images'));
});

/**
 * 配置数据复制
 * @param  {[type]} )
 * @return {[type]}   [description]
 */
gulp.task('data', function() {
    return gulp.src('src/data/*.*')
        .pipe(gulp.dest(path.join(targetDir, 'data')));
});

/**
 * js代码检测
 * @param  {[type]}
 * @return {[type]}       [description]
 */
gulp.task('jshint', function() {
    return gulp
        .src('src/scripts/**/*.js')
        .pipe(plugins.jshint())
        .pipe(plugins.jshint.reporter(stylish));
});

/**
 * 注入样式、第三方js、项目js到index.html中
 * @param  {String}
 * @return {[type]}   [description]
 */
gulp.task('inject', ['jshint', 'styles', 'vendor', 'scripts'], function() {
    var cssNaming = 'styles/main*';
    var _inject = function(src, tag) {
        return plugins.inject(src, {
            starttag: '<!-- inject:' + tag + ':{{ext}} -->',
            read: false,
            addRootSlash: false
        });
    };

    var _getAllScriptSources = function() {
        var scriptStream = gulp.src(['scripts/app.js', 'scripts/**/*.js'], {
            cwd: targetDir
        });
        return streamqueue({
            objectMode: true
        }, scriptStream);
    };

    return gulp.src(['dist/**/*.json', 'src/index.html'])
        .pipe(plugins.revCollector())
        .pipe(plugins.if(build,
            plugins.injectString.after('<!--html5mode-->',
                '\n<base href="/index.html">\n')))
        .pipe(_inject(gulp.src(cssNaming, {
            cwd: targetDir
        }), 'app-styles'))
        .pipe(_inject(gulp.src('vendor*.js', {
            cwd: targetDir
        }), 'vendor'))
        .pipe(plugins.if(build,
            _inject(gulp.src('scripts/app*.js', {
                cwd: targetDir
            }), 'app'),
            _inject(_getAllScriptSources(), 'app')))
        .pipe(plugins.if(build, plugins.minifyHtml({
            empty: true,
            spare: true,
            quotes: true
        })))
        .pipe(gulp.dest(targetDir));
});

/**
 * 监听文件变化实时更新页面
 * @param  {[type]}
 * @return {[type]}   [description]
 */
gulp.task('watchers', function() {
    plugins.livereload.listen();
    gulp.watch('src/styles/**/*.scss', ['styles']);
    gulp.watch('src/fonts/**', ['fonts']);
    gulp.watch('src/images/**', ['images']);
    gulp.watch('src/data/**', ['data']);
    gulp.watch('src/scripts/**/*.js', ['scripts']);
    gulp.watch('./vendor.json', ['vendor']);
    gulp.watch('src/views/**/*.html', ['scripts']);
    gulp.watch('src/index.html', ['inject']);
    gulp.watch(targetDir + '/**')
        .on('change', plugins.livereload.changed);
});

/**
 * 删除编译目录
 * @param  {[type]}
 * @return {[type]}   [description]
 */
gulp.task('clean', function(done) {
    return del([targetDir, 'dist'], done);
});

/**
 * 空任务
 * @param  {[type]}
 * @return {[type]}   [description]
 */
gulp.task('noop', function() {});

/**
 * 默认任务
 * @param  {[type]}
 * @return {[type]}       [description]
 */
gulp.task('default', function(done) {
    if (args.help) {
        gulp.start('help');
    } else {
        runSequence(
            'clean', ['fonts', 'images', 'data'],
            'inject',
            build ? 'noop' : 'watchers',
            build ? 'noop' : 'serve',
            done);
    }
});
